import { chromium, FullConfig } from '@playwright/test';
import path from 'path';
import { spawn, ChildProcess } from 'child_process';

let tauriProcess: ChildProcess | null = null;

async function globalSetup(config: FullConfig) {
  console.log('🚀 Starting global setup for E2E tests...');

  // 构建 Tauri 应用（如果需要）
  if (process.env.BUILD_TAURI) {
    console.log('📦 Building Tauri application...');
    await buildTauriApp();
  }

  // 启动 Tauri 应用进程
  if (process.env.START_TAURI_PROCESS) {
    console.log('🔧 Starting Tauri process...');
    await startTauriProcess();
  }

  // 设置测试数据库
  await setupTestDatabase();

  // 清理测试环境
  await cleanupTestEnvironment();

  console.log('✅ Global setup completed');
}

async function buildTauriApp(): Promise<void> {
  return new Promise((resolve, reject) => {
    const buildProcess = spawn('npm', ['run', 'tauri:build'], {
      stdio: 'inherit',
      cwd: process.cwd(),
    });

    buildProcess.on('close', (code) => {
      if (code === 0) {
        console.log('✅ Tauri build completed successfully');
        resolve();
      } else {
        reject(new Error(`Tauri build failed with code ${code}`));
      }
    });

    buildProcess.on('error', (error) => {
      reject(new Error(`Failed to start Tauri build: ${error.message}`));
    });
  });
}

async function startTauriProcess(): Promise<void> {
  const binaryPath = getBinaryPath();
  
  if (!binaryPath) {
    throw new Error('Tauri binary not found');
  }

  return new Promise((resolve, reject) => {
    tauriProcess = spawn(binaryPath, [], {
      stdio: 'pipe',
      env: {
        ...process.env,
        RUST_LOG: 'debug',
        TAURI_DEBUG: 'true',
      },
    });

    let startupTimeout: NodeJS.Timeout;

    tauriProcess.stdout?.on('data', (data) => {
      const output = data.toString();
      console.log(`Tauri stdout: ${output}`);
      
      // 检查应用是否已启动
      if (output.includes('App started') || output.includes('Window created')) {
        clearTimeout(startupTimeout);
        resolve();
      }
    });

    tauriProcess.stderr?.on('data', (data) => {
      const output = data.toString();
      console.error(`Tauri stderr: ${output}`);
    });

    tauriProcess.on('error', (error) => {
      clearTimeout(startupTimeout);
      reject(new Error(`Failed to start Tauri process: ${error.message}`));
    });

    tauriProcess.on('close', (code) => {
      console.log(`Tauri process exited with code ${code}`);
    });

    // 设置启动超时
    startupTimeout = setTimeout(() => {
      reject(new Error('Tauri process startup timeout'));
    }, 30000);
  });
}

function getBinaryPath(): string | null {
  const platform = process.platform;
  const arch = process.arch;
  
  let binaryName = 'tauri-modern-template';
  if (platform === 'win32') {
    binaryName += '.exe';
  }

  // 尝试不同的路径
  const possiblePaths = [
    path.join(process.cwd(), 'src-tauri', 'target', 'debug', binaryName),
    path.join(process.cwd(), 'src-tauri', 'target', 'release', binaryName),
    path.join(process.cwd(), 'target', 'debug', binaryName),
    path.join(process.cwd(), 'target', 'release', binaryName),
  ];

  for (const binaryPath of possiblePaths) {
    try {
      require('fs').accessSync(binaryPath, require('fs').constants.F_OK);
      return binaryPath;
    } catch (error) {
      // 继续尝试下一个路径
    }
  }

  return null;
}

async function setupTestDatabase(): Promise<void> {
  console.log('🗄️ Setting up test database...');
  
  // 创建测试数据目录
  const testDataDir = path.join(process.cwd(), 'test-data');
  try {
    require('fs').mkdirSync(testDataDir, { recursive: true });
  } catch (error) {
    // 目录可能已存在
  }

  // 设置环境变量
  process.env.TAURI_TEST_DATA_DIR = testDataDir;
  process.env.DATABASE_URL = path.join(testDataDir, 'test.db');
}

async function cleanupTestEnvironment(): Promise<void> {
  console.log('🧹 Cleaning up test environment...');
  
  // 清理旧的测试数据
  const testDataDir = path.join(process.cwd(), 'test-data');
  try {
    require('fs').rmSync(testDataDir, { recursive: true, force: true });
    require('fs').mkdirSync(testDataDir, { recursive: true });
  } catch (error) {
    console.warn('Failed to cleanup test data directory:', error);
  }

  // 清理测试结果目录
  const testResultsDir = path.join(process.cwd(), 'test-results');
  try {
    require('fs').rmSync(testResultsDir, { recursive: true, force: true });
    require('fs').mkdirSync(testResultsDir, { recursive: true });
  } catch (error) {
    console.warn('Failed to cleanup test results directory:', error);
  }
}

// 导出清理函数供 global-teardown 使用
export async function globalCleanup(): Promise<void> {
  console.log('🧹 Starting global cleanup...');

  // 停止 Tauri 进程
  if (tauriProcess) {
    console.log('🛑 Stopping Tauri process...');
    tauriProcess.kill('SIGTERM');
    
    // 等待进程结束
    await new Promise<void>((resolve) => {
      if (!tauriProcess) {
        resolve();
        return;
      }

      const timeout = setTimeout(() => {
        console.warn('Force killing Tauri process...');
        tauriProcess?.kill('SIGKILL');
        resolve();
      }, 5000);

      tauriProcess.on('close', () => {
        clearTimeout(timeout);
        resolve();
      });
    });
  }

  // 清理测试数据
  await cleanupTestEnvironment();

  console.log('✅ Global cleanup completed');
}

export default globalSetup;
